//这是关于多线程测试的代码
#include<iostream>
#include<pthread.h>//线程库
#include<string>
#include<unistd.h>

//testdemo1 看看他们的线程id是否相同  结果：他们的线程id是不同的

// void* func(void* args)
// {
//     std::string name = (char*)args;//转化为字符串
//     while(1)
//     {
//         std::cout<<"thread name:"<<name<<"id:"<<pthread_self()<<std::endl;
//         sleep(1);
//     }
// }
// int main()
// {
//     pthread_t tid;//线程id，实际上是该线程结构体在动态库中的起始地址
//     pthread_create(&tid,nullptr,func,(void*)"thread-1");//参数解析：1.线程id，输出型参数 2.线程的属性，nullptr使用默认属性 
//     //3.该线程的入口地址，也就是说要让这个线程执行的任务是什么 4.传给线程启动的参数可以是任意类型的

//     //main线程
//     while(1)
//     {
//         std::cout<<"main id:"<<pthread_self()<<std::endl;
//         sleep(1);
//     }
//     return 0;
// }


//testdemo2   测试pid是否相同  结果：是相同的，所以操作系统在进行线程调度时可以根据他们的pid来确认是否为同一个进程内的线程

// void* func(void* args)
// {
//     std::string name = (char*)args;//转化为字符串
//     while(1)
//     {
//         std::cout<<"thread name:"<<name<<"id:"<<getpid()<<std::endl;
//         sleep(1);
//     }
// }
// int main()
// {
//     pthread_t tid;//线程id，实际上是该线程结构体在动态库中的起始地址
//     pthread_create(&tid,nullptr,func,(void*)"thread-1");//参数解析：1.线程id，输出型参数 2.线程的属性，nullptr使用默认属性 
//     //3.该线程的入口地址，也就是说要让这个线程执行的任务是什么 4.传给线程启动的参数可以是任意类型的

//     //main线程
//     while(1)
//     {
//         std::cout<<"main id:"<<getpid()<<std::endl;
//         sleep(1);
//     }
//     return 0;
// }


//testdemo3 线程终止的三种情况 线程也需要被等待

// void* func(void* args)
// {
//     std::string name = (char*)args;//转化为字符串
//     int cnt = 5;
//     while(1)
//     {
//         std::cout<<"thread name:"<<name<<"id:"<<getpid()<<std::endl;
//         sleep(1);
//     }
//     //1.return
//     //return (void*)10;
//     //2.void pthread_exit(返回值)用法与return一样
//     //pthread_exit((void*)10);
//     //3.int pthread_cancel(线程id) 成功返回0，失败返回错误码，被取消的线程无法被等待
//     return (void*)10;
// }
// int main()
// {
//     pthread_t tid;//线程id，实际上是该线程结构体在动态库中的起始地址
//     pthread_create(&tid,nullptr,func,(void*)"thread-1");//参数解析：1.线程id，输出型参数 2.线程的属性，nullptr使用默认属性 
//     //3.该线程的入口地址，也就是说要让这个线程执行的任务是什么 4.传给线程启动的参数可以是任意类型的

//     //main线程
//     sleep(3);
//     pthread_cancel(tid);
//     void* ret=nullptr;
//     int n = pthread_join(tid,&ret);//ret就是线程返回的结果
//     if(ret== PTHREAD_CANCELED)
//     std::cout<<"异常终止"<<std::endl;
//     else
//     std::cout<<"..."<<std::endl;
//     //std::cout<<ret<<std::endl;
//     return 0;
// }


//分离线程  pthread_detach(tid) 被分离的线程不需要被等待，既可以自己分离自己，也可以由main线程分离，分离的线程正常共享进程资源

void* func(void* args)
{
    std::string name = (char*)args;//转化为字符串
    int cnt =5;
    while(cnt--)
    {
        std::cout<<"thread name:"<<name<<"id:"<<getpid()<<std::endl;
        sleep(1);
    }
    return (void*)10;
}
int main()
{
    pthread_t tid;//线程id，实际上是该线程结构体在动态库中的起始地址
    pthread_create(&tid,nullptr,func,(void*)"thread-1");//参数解析：1.线程id，输出型参数 2.线程的属性，nullptr使用默认属性 
    //3.该线程的入口地址，也就是说要让这个线程执行的任务是什么 4.传给线程启动的参数可以是任意类型的

    //main线程
    //分离线程
    sleep(3);
    pthread_detach(tid);
    void* ret = nullptr;
    pthread_join(tid,&ret);
    std::cout<<ret<<std::endl;
    return 0;
}